﻿using System;
using System.IO;
using System.Globalization;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Godot.core
{
    public partial class Variant
    {
        public const int VARIANT_ARG_MAX = 5;

        public delegate void VariantFunc(ref Variant r_ret, ref Variant p_self, Variant[] p_args);

        public delegate void VariantConstructFunc(ref Variant r_ret, Variant[] p_args);

        public class VariantCall
        {
            #region ____ nested classes ____
            public class FuncData
            {          
		        public int arg_count;
		        public List<Variant> default_args;
		        public List<Variant.Type> arg_types;

                public VariantFunc func;

                public FuncData()
                {
                    default_args = new List<Variant>();
                    arg_types = new List<Type>();
                }

                public void call(ref Variant r_ret, ref Variant p_self, Variant[] p_args, ref Variant.CallError r_error)
                {
                    if (p_args.Length < arg_count)
                    {
                        int def_argcount = default_args.Count;

                        if (p_args.Length > Variant.VARIANT_ARG_MAX)
                            return;

                        Variant[] newargs = new Variant[Variant.VARIANT_ARG_MAX];

                        for (int i = 0; i < p_args.Length; i++)
                            newargs[i] = p_args[i];

                        int defargcount = def_argcount;

                        for (int i = p_args.Length; i < arg_count; i++)
                            newargs[i] = default_args[defargcount - (i - p_args.Length) - 1]; //default arguments

                        func(ref r_ret, ref p_self, newargs);
                    }
                    else
                    {
                        func(ref r_ret, ref p_self, p_args);
                    }
                }
            }

            public class TypeFunc
            {
                public Dictionary<StringName, FuncData> functions;

                public TypeFunc()
                {
                    functions = new Dictionary<StringName, FuncData>();
                }
            }

            public class Arg
            {
                public StringName name;
		        public Variant.Type type;
		        
                public Arg() 
                { 
                    type = Variant.Type.NIL;
                }
		        
                public Arg(Variant.Type p_type, StringName p_name) 
                { 
                    name = p_name; 
                    type = p_type; 
                }
            }

            public class ConstructData
            {
                public int arg_count;
                public List<Variant.Type> arg_types;
                public List<string> arg_names;
                public VariantConstructFunc func;

                public ConstructData()
                {
                    arg_types = new List<Variant.Type>();
                    arg_names = new List<string>();
                }

            };

            public class ConstructFunc
            {
                public List<ConstructData> constructors;
            };

            public class ConstantData
            {
                public Dictionary<StringName, int> value;

                public ConstantData()
                {
                    value = new Dictionary<StringName, int>();
                }
            };
            #endregion

            public static List<ConstantData> constant_data = null;

            public static List<TypeFunc> type_funcs = null;

            public static List<ConstructFunc> construct_funcs = null;

            public static void addfunc(Variant.Type p_type, Variant.Type p_return, StringName p_name, 
                VariantFunc p_func, List<Variant> p_defaultarg, Arg p_argtype1 = null, Arg p_argtype2 = null, 
                Arg p_argtype3 = null, Arg p_argtype4 = null, Arg p_argtype5 = null)
            {
                FuncData funcdata = new FuncData();
                funcdata.func = p_func;
                funcdata.default_args = p_defaultarg;

                if (p_argtype1 != null ? p_argtype1.name != null : false)
                    funcdata.arg_types.Add(p_argtype1.type);           
                else
                    goto end;

                if (p_argtype2 != null ? p_argtype2.name != null : false)
                    funcdata.arg_types.Add(p_argtype2.type);
                else
                    goto end;

                if (p_argtype3 != null ? p_argtype3.name != null : false)
                    funcdata.arg_types.Add(p_argtype3.type);
                else
                    goto end;

                if (p_argtype4 != null ? p_argtype4.name != null : false)
                    funcdata.arg_types.Add(p_argtype4.type);
                else
                    goto end;

                if (p_argtype5 != null ? p_argtype5.name != null : false)
                    funcdata.arg_types.Add(p_argtype5.type);
                else
                    goto end;

                /*label*/end: 

                funcdata.arg_count = funcdata.arg_types.Count;
                VariantCall.type_funcs[(int)p_type].functions[p_name] = funcdata;
            }

            #region ____ built-in functions of localmem based types ____
            internal static List<Variant> varray(Variant p_arg1 = null , Variant p_arg2 = null, Variant p_arg3 = null, Variant p_arg4 = null, Variant p_arg5 = null)
            {
                List<Variant> res = new List<Variant>();
                if (p_arg1 != null) res.Add(p_arg1);
                if (p_arg2 != null) res.Add(p_arg2);
                if (p_arg3 != null) res.Add(p_arg3);
                if (p_arg4 != null) res.Add(p_arg4);
                if (p_arg5 != null) res.Add(p_arg5);

                if (res.Count == 0) return null;
                return res;
            }

            internal static void call_String_casecmp_to(ref Variant r_ret,ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).CompareTo(p_args[0]);
            }

            internal static void call_String_nocasecmp_to(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = string.Compare((string)p_self, (string)p_args[0], true);
            }

            internal static void call_String_length(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).Length;
            }

            internal static void call_String_substr(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).Substring(p_args[0], p_args[1]);
            }

            internal static void call_String_find(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).IndexOf((string)p_args[0], (int)p_args[1]);
            }

            internal static void call_String_find_last(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).LastIndexOf((string)p_args[0]);
            }

            internal static void call_String_findn(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).IndexOf((string)p_args[0], (int)p_args[1], StringComparison.OrdinalIgnoreCase);
            }

            internal static void call_String_rfind(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = -1;
            }

            internal static void call_String_rfindn(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = -1;
            }

            internal static void call_String_match(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = System.Text.RegularExpressions.Regex.IsMatch((string)p_args[0], (string)p_self);
            }

            internal static void call_String_matchn(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = System.Text.RegularExpressions.Regex.IsMatch((string)p_args[0], (string)p_self, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            }

            internal static void call_String_begins_with(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).StartsWith((string)p_args[0]);
            }

            internal static void call_String_replace(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).Replace((string)p_args[0], (string)p_args[1]);
            }

            internal static void call_String_replacen(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                string source = (string)p_self;
                string oldString = (string)p_args[0];
                int index = source.IndexOf(oldString, StringComparison.OrdinalIgnoreCase);

                // Determine if we found a match
                bool MatchFound = index >= 0;

                if (MatchFound)
                {
                    // Remove the old text
                    source = source.Remove(index, oldString.Length);

                    // Add the replacemenet text
                    source = source.Insert(index, (string)p_args[1]);
                }

                r_ret = source;
            }

            internal static void call_String_insert(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).Insert((int)p_args[0], (string)p_args[1]);
            }

            internal static void call_String_capitalize(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = CultureInfo.GetCultureInfo("en-US").TextInfo.ToTitleCase((string)p_self);
            }

            internal static void call_String_split(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                string[] res = ((string)p_self).Split(new string[] { (string)p_args[0] }, ((bool)p_args[1]) ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries);
                r_ret = (Variant) new List<string>(res);
            }

            internal static void call_String_split_floats(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                List<double> res = new List<double>();
                string[] res_str = ((string)p_self).Split(new string[] { (string)p_args[0] }, ((bool)p_args[1]) ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries);
                for(int i = 0; i < res_str.Length; i++)
                {
                    res.Add(double.Parse(res_str[i]));
                }
                r_ret = res;
            }

            internal static void call_String_to_upper(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).ToUpper();
            }

            internal static void call_String_to_lower(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).ToLower();
            }

            internal static void call_String_left(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                int p_pos = p_args[0];

                if (p_pos <= 0)
                {
                    r_ret = "";
                    return;
                }

                if (p_pos >= ((string)p_self).Length)
                {
                    r_ret = (string)p_self;
                    return;
                }

                r_ret = ((string)p_self).Substring(0, p_pos);
            }

            internal static void call_String_right(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                int p_pos = p_args[0];

                if (p_pos >= ((string)p_self).Length)
                {
                    r_ret = (string)p_self;
                    return;
                }

                if (p_pos < 0)
                {
                    r_ret = "";
                    return;
                }

                r_ret = ((string)p_self).Substring(p_pos + 1, (((string)p_self).Length - p_pos) - 1);
            }

            internal static void call_String_strip_edges(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).strip_edges();
            }

            internal static void call_String_extension(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = Path.GetExtension((string)p_self);
            }

            internal static void call_String_basename(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = Path.GetFileNameWithoutExtension((string)p_self);
            }

            internal static void call_String_plus_file(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                string self = p_self;
                if (self.Length > 0 && self[self.Length - 1] == '/')
		            r_ret = self + ((string)p_args[0]);
	            else
		            r_ret = self + "/" + ((string)p_args[0]);
            }

            internal static void call_String_ord_at(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = "" + ((string)p_self)[(int)p_args[0]];
            }

            internal static void call_String_hash(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).GetHashCode();
            }

            internal static void call_String_empty(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).Length == 0;
            }

            internal static void call_String_is_abs_path(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).is_abs_path();
            }

            internal static void call_String_is_rel_path(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).is_rel_path();
            }

            internal static void call_String_get_base_dir(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).get_base_dir();
            }

            internal static void call_String_get_file(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                string self = p_self;

                int sep = Math.Max(self.LastIndexOf("/"), self.LastIndexOf("\\"));

                if (sep == -1)
                    r_ret = self;
                else
                    r_ret =  self.Substring(sep + 1, self.Length);
            }

            internal static void call_String_xml_escape(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).xml_escape();
            }

            internal static void call_String_xml_unescape(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).xml_unescape();
            }

            internal static void call_String_percent_encode(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).percent_encode();
            }
            
            internal static void call_String_percent_decode(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).percent_decode();
            }

            internal static void call_String_is_valid_identifier(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).is_valid_identifier();
            }

            internal static void call_String_is_valid_integer(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).is_valid_integer();
            }

            internal static void call_String_is_valid_float(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).is_valid_float();
            }

            internal static void call_String_is_valid_html_color(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).is_valid_html_color();
            }

            internal static void call_String_is_valid_ip_address(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).is_valid_ip_address();
            }

            internal static void call_String_to_int(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = int.Parse((string)p_self);
            }

            internal static void call_String_to_float(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = double.Parse((string)p_self);
            }

            internal static void call_String_hex_to_int(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = int.Parse((string)p_self, NumberStyles.HexNumber);
            }

            internal static void call_String_pad_decimals(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).pad_decimals(p_args[0]);
            }

            internal static void call_String_pad_zeros(ref Variant r_ret, ref Variant p_self, Variant[] p_args)
            {
                r_ret = ((string)p_self).pad_zeros(p_args[0]);
            }
            #endregion
        }

        public static void register_variant_methods()
        {
            VariantCall.type_funcs = Enumerable.Repeat<VariantCall.TypeFunc>(new VariantCall.TypeFunc(), (int)Variant.Type.VARIANT_MAX).ToList();
            VariantCall.construct_funcs = new List<VariantCall.ConstructFunc>((int)Variant.Type.VARIANT_MAX);
            VariantCall.constant_data = new List<VariantCall.ConstantData>((int)Variant.Type.VARIANT_MAX);

            #region ____ String variant call _____
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.INT, "casecmp_to", VariantCall.call_String_casecmp_to, VariantCall.varray(), new VariantCall.Arg(Variant.Type.STRING, "to"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.INT, "nocasecmp_to", VariantCall.call_String_nocasecmp_to, VariantCall.varray(), new VariantCall.Arg(Variant.Type.STRING, "to"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.INT, "length", VariantCall.call_String_length, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "substr", VariantCall.call_String_substr, VariantCall.varray(), new VariantCall.Arg(Variant.Type.INT, "from"), new VariantCall.Arg(Variant.Type.INT, "len"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.INT, "find", VariantCall.call_String_find, VariantCall.varray(0), new VariantCall.Arg(Variant.Type.STRING, "what"), new VariantCall.Arg(Variant.Type.INT, "from"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.INT, "find_last", VariantCall.call_String_find_last, VariantCall.varray(), new VariantCall.Arg(Variant.Type.STRING, "what"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.INT, "findn", VariantCall.call_String_findn, VariantCall.varray(0), new VariantCall.Arg(Variant.Type.STRING, "what"), new VariantCall.Arg(Variant.Type.INT, "from"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.INT, "rfind", VariantCall.call_String_rfind, VariantCall.varray(-1), new VariantCall.Arg(Variant.Type.STRING, "what"), new VariantCall.Arg(Variant.Type.INT, "from"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.INT, "rfindn", VariantCall.call_String_rfindn, VariantCall.varray(-1), new VariantCall.Arg(Variant.Type.STRING, "what"), new VariantCall.Arg(Variant.Type.INT, "from"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.BOOL, "match", VariantCall.call_String_match, VariantCall.varray(), new VariantCall.Arg(Variant.Type.STRING, "expr"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.BOOL, "matchn", VariantCall.call_String_matchn, VariantCall.varray(), new VariantCall.Arg(Variant.Type.STRING, "expr"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.BOOL, "begins_with", VariantCall.call_String_begins_with, VariantCall.varray(), new VariantCall.Arg(Variant.Type.STRING, "text"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "replace", VariantCall.call_String_replace, VariantCall.varray(), new VariantCall.Arg(Variant.Type.STRING, "what"), new VariantCall.Arg(Variant.Type.STRING, "forwhat"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "replacen", VariantCall.call_String_replace, VariantCall.varray(), new VariantCall.Arg(Variant.Type.STRING, "what"), new VariantCall.Arg(Variant.Type.STRING, "forwhat"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "insert", VariantCall.call_String_insert, VariantCall.varray(), new VariantCall.Arg(Variant.Type.INT, "pos"), new VariantCall.Arg(Variant.Type.STRING, "what"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "capitalize", VariantCall.call_String_capitalize, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING_ARRAY, "split", VariantCall.call_String_split, VariantCall.varray(true), new VariantCall.Arg(Variant.Type.STRING, "divisor"), new VariantCall.Arg(Variant.Type.BOOL, "allow_empty"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.REAL_ARRAY, "split_floats", VariantCall.call_String_split_floats, VariantCall.varray(true), new VariantCall.Arg(Variant.Type.STRING, "divisor"), new VariantCall.Arg(Variant.Type.BOOL, "allow_empty"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "to_upper", VariantCall.call_String_to_upper, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "to_lower", VariantCall.call_String_to_lower, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "left", VariantCall.call_String_left, VariantCall.varray(), new VariantCall.Arg(Variant.Type.INT, "pos"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "right", VariantCall.call_String_right, VariantCall.varray(), new VariantCall.Arg(Variant.Type.INT, "pos"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "strip_edges", VariantCall.call_String_strip_edges, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "extension", VariantCall.call_String_extension, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "basename", VariantCall.call_String_basename, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "plus_file", VariantCall.call_String_plus_file, VariantCall.varray(), new VariantCall.Arg(Variant.Type.STRING, "file"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "ord_at", VariantCall.call_String_ord_at, VariantCall.varray(), new VariantCall.Arg(Variant.Type.INT, "at"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.INT, "hash", VariantCall.call_String_hash, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.BOOL, "empty", VariantCall.call_String_empty, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.BOOL, "is_abs_path", VariantCall.call_String_is_abs_path, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.BOOL, "is_rel_path", VariantCall.call_String_is_rel_path, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "get_base_dir", VariantCall.call_String_get_base_dir, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "get_file", VariantCall.call_String_get_file, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "xml_escape", VariantCall.call_String_xml_escape, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "xml_unescape", VariantCall.call_String_xml_unescape, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "percent_encode", VariantCall.call_String_percent_encode, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "percent_decode", VariantCall.call_String_percent_decode, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.BOOL, "is_valid_identifier", VariantCall.call_String_is_valid_identifier, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.BOOL, "is_valid_integer", VariantCall.call_String_is_valid_integer, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.BOOL, "is_valid_float", VariantCall.call_String_is_valid_float, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.BOOL, "is_valid_html_color", VariantCall.call_String_is_valid_html_color, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.BOOL, "is_valid_ip_address", VariantCall.call_String_is_valid_ip_address, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.INT, "to_int", VariantCall.call_String_to_int, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.REAL, "to_float", VariantCall.call_String_to_float, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.INT, "hex_to_int", VariantCall.call_String_hex_to_int, VariantCall.varray());
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "pad_decimals", VariantCall.call_String_pad_decimals, VariantCall.varray(), new VariantCall.Arg(Variant.Type.INT, "digits"));
            VariantCall.addfunc(Variant.Type.STRING, Variant.Type.STRING, "pad_zeros", VariantCall.call_String_pad_zeros, VariantCall.varray(), new VariantCall.Arg(Variant.Type.INT, "digits"));
            #endregion
        }
    }
}
